#include "MyWifi.h"
#ifndef WIN32
#include <Wifi.h>
#include <Arduino.h>
#include "nvs_flash.h"
#include "esp_wifi.h"
#include "config.h"
#include "WiFiSTA.h"
extern TaskHandle_t gWifiPerTaskHandle;
#endif

WIFI_STATE wifiState = WIFI_STAT_INIT;
void wifi_clear(void)
{
  #ifndef WIN32
  esp_wifi_restore();
  nvs_flash_erase();
  nvs_flash_init();
  Serial.println("wifi_clear ok");
  #endif
}

void wifi_printInfo()
{
  #ifndef WIN32
  if (WiFi.status() == WL_CONNECTED)
  {
    // 使用\r\n不能换行，不知道为啥
    printf("wifi已连接\n");
    Serial.print("IP:");
    Serial.println(WiFi.localIP());
    printf("SSID:%s\n", WiFi.SSID().c_str());
    printf("PSW:%s\n", WiFi.psk().c_str());
    printf("DNS1: %s\n", WiFi.dnsIP(0).toString().c_str());
    printf("DNS2: %s\n", WiFi.dnsIP(1).toString().c_str());
  }
  else
  {
    Serial.println("wifi未连接");
  }
  #endif
}

// WiFi扫描功能实现
int wifi_is_exist(const char* ssid,char printSw)
{
  #ifndef WIN32
  Serial.println("开始WiFi扫描...");
  WiFi.disconnect();
  int retry = 0;
  int n = -1;

  // 确保Wi-Fi已经启用并处于正确模式
    if (!WiFi.enableSTA(true)) {
        Serial.println("无法启用STA模式");
        return -1;
    }
    else
    {
      Serial.println("可以启用STA模式");
    }

    // 检查是否已经在扫描中
    if (WiFi.scanComplete() == WIFI_SCAN_RUNNING) {
        Serial.println("扫描已在进行中，等待完成...");
        unsigned long start = millis();
        while (WiFi.scanComplete() == WIFI_SCAN_RUNNING && (millis() - start) < 10000) {
            delay(100);
        }
    }


  // 尝试扫描，最多重试3次
  while (n < 0 && retry < 3) {
    n = WiFi.scanNetworks(false, false); // 阻塞式扫描，不隐藏网络
    if (n == WIFI_SCAN_RUNNING) {
            // 如果正在扫描中，等待完成
            unsigned long start = millis();
            while (n == WIFI_SCAN_RUNNING && (millis() - start) < 10000) {
                delay(100);
                n = WiFi.scanComplete();
            }
        }
    if (n < 0) {
      Serial.println("扫描失败，错误代码: " + String(n) + " 重试中... ("+ String(retry+1) + "/3)");
      delay(1000);
      retry++;
    }
  }
  
  if (n <= 0) {
    Serial.println("WiFi扫描失败");
    // wifiScanState = WIFI_SCAN_ERROR;
    // wifiScanCount = 0;
    return -1;
  }
  
  Serial.println("找到 "+ String(n) +  " 个WiFi网络\n");
  int wifiScanCount = (n > 20) ? 20 : n; // 最多存储20个网络
  char flag = 0;
  for (int i = 0; i < wifiScanCount; i++) {
    if(printSw == 1)
    {
      Serial.println(String(i + 1) + " : " + WiFi.SSID(i) + "(" + WiFi.RSSI(i) +"dBm)" );
    }
    if(strcmp(ssid, WiFi.SSID(i).c_str()) == 0)
    {
      flag = 1;
    }
  }
  
  WiFi.scanDelete(); // 删除扫描结果以释放内存
  // wifiScanState = WIFI_SCAN_DONE;
  Serial.println("WiFi扫描完成");
  if(flag == 1)
  {
    return 0;
  }
  #endif
  return -1;
}

void wifi_detStat()
{
  #ifndef WIN32
  int timeout = 0;
  while (timeout < WIFI_CONNECT_TIMEOUT)
  {
    Serial.print(".");
    delay(WIFI_SMART_TIMEOUT_PER);
    if (WiFi.status() == WL_CONNECTED)
    {
      wifiState = WIFI_STAT_CONNECT;
      break;
    }
    timeout += WIFI_SMART_TIMEOUT_PER;
  }
  if(timeout >= WIFI_CONNECT_TIMEOUT)
  {
    wifiState = WIFI_STAT_DISCONNECT;
  }
  wifi_printInfo();
  #endif
}

void wifi_reconnect(char reInit = 1)
{
  #ifndef WIN32
  if (WiFi.status() == WL_CONNECTED)
  {
    return;
  }
  wifi_config_t current_conf;
  memset(&current_conf, 0, sizeof(wifi_config_t));
  esp_err_t err = ESP_OK;
  char flag = 1;
  wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
  if(reInit == 1)
  {
    if((err = esp_wifi_init(&cfg)) != ESP_OK)
    {
      Serial.println("esp_wifi_init error : " + String(err));
    }
  }
  WiFi.mode(WIFI_STA);
  if((err = esp_wifi_get_config((wifi_interface_t)ESP_IF_WIFI_STA, &current_conf)) != ESP_OK )
  {
      flag = 0;
      Serial.println("esp_wifi_get_config error : " + String(err));
  }
  else
  {
    log_e("get nvs wifi ssid %s psw : %s ok!",current_conf.sta.ssid,current_conf.sta.password);
    if(current_conf.sta.ssid[0] == 0)
    {
      flag = 0;
    }
  }
  #if defined(SSIDNAME) && defined(PASSWORD)
  Serial.println("尝试连接1 SSID:" + String(SSIDNAME) + " PSW:" + String(PASSWORD));
  if(wifi_is_exist(SSIDNAME,1) != 0)
  {
    Serial.println("附近没有 ssid : " + String(SSIDNAME)  + " 的WiFi");
  }
  else
  {
     WiFi.begin(SSIDNAME, PASSWORD);
     wifi_detStat();
  }
 
  if (WiFi.status() != WL_CONNECTED && flag)
  {
      Serial.println("尝试连接2 SSID:" + String((const char *)current_conf.sta.ssid) + " PSW:" + String((const char *)current_conf.sta.password));
      if(esp_wifi_set_config((wifi_interface_t)ESP_IF_WIFI_STA, &current_conf) != ESP_OK)
      {
          log_e("recover wifi ssid %s psw : %s failed!",current_conf.sta.ssid,current_conf.sta.password);
      }  
      else
      {
          log_e("recover wifi ssid %s psw : %s ok!",current_conf.sta.ssid,current_conf.sta.password);
      }
      wifiState = WIFI_STAT_INIT;

       if(wifi_is_exist((const char*)current_conf.sta.ssid,1) != 0)
        {
          printf("附近没有 ssid : %s 的WiFi\n",current_conf.sta.ssid);
        }
        else
        {
          WiFi.begin();
          wifi_detStat();
        }
  }
 
#else
  if(flag != 0)
  {
      printf("尝试连接 SSID:%s PSW:%s\n",current_conf.sta.ssid, current_conf.sta.password);
      WiFi.begin();
      wifi_detStat();
  }
#endif

#endif
}

void wifi_setup(void)
{
  #ifndef WIN32
  wifiState = WIFI_STAT_INIT;
  wifi_reconnect(1);
  // wifi_printInfo();
  #endif
}

void wifi_perTask(void *pvParameters)
{
  #ifndef WIN32
  wifi_setup();
  const TickType_t xFrequency = pdMS_TO_TICKS(1000);
  TickType_t xLastWakeTime;
  xLastWakeTime = xTaskGetTickCount();
  int rssi_total;
  const int rssi_avg_count = 50;
  while(1)
  {
    // 检测WIFI信号
    if (WiFi.status() == WL_CONNECTED)
    {
      #if 0
      rssi_total = 0;
      for (uint16_t i = 0; i < rssi_avg_count; i++)
      {
        rssi_total = rssi_total + WiFi.RSSI();
        vTaskDelay(1);
      }
      system_data.hardware_data.rssi = rssi_total / rssi_avg_count;
      #endif
    }
    else
    {
      printf("WIFI断开,重新连接\n");
      wifiState = WIFI_STAT_DISCONNECT;
      wifi_reconnect();
      delay(120000);
    }
    vTaskDelayUntil(&xLastWakeTime, xFrequency);
  }
  #endif
}

void wifi_smartTask(void *pvParameters)
{
  #ifndef WIN32
  int timeout = 0;
  while (1)
  {
    timeout = 0;
    // flase 计数信号量 true 二进制信号量
    ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
    vTaskSuspend(gWifiPerTaskHandle);
    wifiState = WIFI_STAT_SMART;
    if (WiFi.mode(WIFI_AP_STA) != true)
    {
      Serial.println("WiFi mode error");
      // return;
    }
    // printf("Wait for Smartconfig...\n");
    Serial.println("Wait for Smartconfig...");
    if (WiFi.beginSmartConfig(SC_TYPE_ESPTOUCH_AIRKISS) != true)
    {
      Serial.println("WiFi beginSmartConfig error");
      // return;
    }

    while (timeout < WIFI_SMART_TIMEOUT)
    {
      Serial.print("*");
      delay(WIFI_SMART_TIMEOUT_PER);
      if (WiFi.smartConfigDone())
      {
        wifi_printInfo();
        // wifi_config_t conf;
        // memset(&conf, 0, sizeof(wifi_config_t));
        // wifi_sta_config_extern(&conf, WiFi.SSID().c_str(), WiFi.psk().c_str());
        // if(esp_wifi_set_config((wifi_interface_t)ESP_IF_WIFI_STA, &conf) != ESP_OK)
        // {
        //     printf("esp_wifi_set_config error!\n");
        // }
        // wifiState = WIFI_STAT_CONNECT;
        break;
      }
      timeout += WIFI_SMART_TIMEOUT_PER;
    }
     if (timeout >= WIFI_SMART_TIMEOUT)
     {
        Serial.println("\nSmartconfig fail! Exit Smart config mode.");
        wifiState = WIFI_STAT_SMART_FAIL;
     }
     else
     {
        Serial.println("\nSmartconfig success! Exit Smart config mode.");
        wifiState = WIFI_STAT_SMART_SUCCESS;
     }
    WiFi.stopSmartConfig();
    vTaskResume(gWifiPerTaskHandle);
  }
  #endif
}

WIFI_STATE wifi_getStat()
{
  return wifiState;
}

int wifi_setStat(WIFI_STATE stat)
{
  if(stat < WIFI_STAT_INIT || stat >= WIFI_STAT_MAX)
  {
    return -1;
  }
  wifiState = stat;
  return 0;
}


const char *wifi_get_ssid()
{
  static char ssid_buffer[32]; // 用于存储ssid的静态缓冲区
  #ifndef WIN32
  if(WiFi.SSID() != "" )
  {
    strncpy(ssid_buffer, WiFi.SSID().c_str(), sizeof(ssid_buffer) - 1);
    ssid_buffer[sizeof(ssid_buffer) - 1] = '\0'; // 确保字符串结束
    // printf("SSID:%s\n", ssid_buffer);
    return ssid_buffer;
  }
  // printf("SSID: NULL 未连接\n");
  strncpy(ssid_buffer, "未连接", sizeof(ssid_buffer) - 1);
  ssid_buffer[sizeof(ssid_buffer) - 1] = '\0'; // 确保字符串结束
  #else
  #ifdef SSIDNAME
  sprintf(ssid_buffer,"%s",SSIDNAME);
  #else
  sprintf(ssid_buffer,"%s","test");
  #endif
  #endif
  return ssid_buffer;
}
